// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
/** \file
    \brief Solve MHD equation utilizing discontinous galkin
*/
// always include the config file
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
// dune-common includes
#include <dune/common/parallel/mpihelper.hh> // An initializer of MPI
#include <dune/common/exceptions.hh> // We use exceptions
#include <dune/common/parametertreeparser.hh>
#include <iostream>
#include <map>
// compose a simulation code
#include <dune/compose/compose.hh>

int main(int argc, char** argv)
{
  try{
    // Maybe initialize MPI
    Dune::MPIHelper& helper = Dune::MPIHelper::instance(argc, argv);
    std::cout << "This is demo of mhd simulation code utilizing discontinous galkin method, build upon dune and dune-pdelab." << std::endl;
    if(Dune::MPIHelper::isFake)
      std::cout<< "This is a sequential program." << std::endl;
    else
      std::cout<<"I am rank "<<helper.rank()<<" of "<<helper.size()
        <<" processes!"<<std::endl;

    /** 
     * open .ini file for a test
     * usage: ./executable -ini sound-wave.ini
     */
    Dune::ParameterTree ptree;
    Dune::ParameterTreeParser ptreeparser;
    ptreeparser.readOptions(argc,argv,ptree);
    ptreeparser.readINITree(ptree.get<std::string>("ini"),ptree);
    // ptreeparser.readINITree("sound-wave.ini",ptree); 

    /**  
     * assign initial condition from TestSuite
     */
    Dune::Initial::InitialBase* initial;
    const std::string collectername = ptree.get<std::string>("initial.collectername");
    std::map<std::string, int> collectermap = {
      {"ConstantAdvection",1},
      {"SoundWave",2},
      {"ShallowWater",3},
      {"Euler",4},
      {"MHD",5}
    };
    int collectervalue = collectermap[collectername];
    switch (collectervalue) {
    case 1:
      initial = new Dune::Initial::ConstantAdvection(ptree);   
      break;
    case 2:
      initial = new Dune::Initial::SoundWave(ptree);   
      break;
    case 3:
      initial = new Dune::Initial::ShallowWater(ptree);   
      break;
    case 4:
      initial = new Dune::Initial::Euler(ptree);   
      break;
    case 5:
      initial = new Dune::Initial::MHD(ptree);   
      break;
    }

    /**
     * assgin boundary condition  
     */
    Dune::Boundary::Boundary* boundaryptr;
    Dune::Boundary::Boundary boundary;
    boundaryptr = &boundary;

    /** 
     * assign equation
     */
    Dune::Compose::assignequation(initial,boundaryptr,ptree); 

    return 0;
  }
  catch (Dune::Exception &e){
    std::cerr << "Dune reported error: " << e << std::endl;
  }
  catch (...){
    std::cerr << "Unknown exception thrown!" << std::endl; 
  }
}
